﻿
using Sharp.Domain.Model;
using Sharp.Domain.Repositories;
using Sharp.Infrastructure;
using Sharp.Infrastructure.Search;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
#if NET462
using System.Web;
#endif


namespace Sharp.Domain.Repository.EF
{
    /// <summary>
    ///     仓储基类
    /// </summary>
    /// <typeparam name="TAggregateRoot"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public partial class Repository<TKey, TAggregateRoot> : IRepository<TKey, TAggregateRoot>
        where TAggregateRoot : class, IAggregateRoot<TKey>
        where TKey : struct
    {
        private readonly IEntityFrameworkRepositoryContext _efContext;
        /// <summary>
        /// 仓储基类
        /// </summary>
        /// <param name="context"></param>
        public Repository(IRepositoryContext context)
        {
#if DEBUG
            if (context == null)
            {
                throw new NotImplementedException("为实例化IRepositoryContext");
            }
#endif
            this._efContext = context as IEntityFrameworkRepositoryContext;
        }
        /// <summary>
        /// 上下文
        /// </summary>
        public IRepositoryContext Context
        {
            get { return _efContext; }
        }
        /// <summary>
        /// DbSet实现
        /// </summary>
        /// <returns></returns>
        protected virtual IQueryable<TAggregateRoot> DbSet()
        {
            var query = _efContext.Context.Set<TAggregateRoot>().Filter();

            query = query.FilterSassData<TKey, TAggregateRoot>();

            return query;
        }
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="aggregateRoot"></param>
        public virtual void Add(TAggregateRoot aggregateRoot)
        {
            ExtraProcessing(aggregateRoot);
            Context.RegisterNew<TKey, TAggregateRoot>(aggregateRoot);
        }
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="aggregateRoots"></param>
        public virtual void Add(IEnumerable<TAggregateRoot> aggregateRoots)
        {
            foreach (var entity in aggregateRoots.ToList())
            {
                ExtraProcessing(entity);
            }
            Context.RegisterNew<TKey, TAggregateRoot>(aggregateRoots);
        }

        /// <summary>
        /// 额外处理
        /// </summary>
        /// <param name="aggregateRoot"></param>
        private void ExtraProcessing(TAggregateRoot aggregateRoot)
        {
            FixData(aggregateRoot);
            if (aggregateRoot is ILogCreatedEntity entity)
            {
                entity.CreatedTime = DateTime.Now;
                entity.CreatedUserId = GetUserId();
            }
            if (aggregateRoot is ILogModifiEntity modifiEntity)
            {
                modifiEntity.ModifiTime = DateTime.Now;
                modifiEntity.ModifiedUserId = GetUserId();
            }
            if (aggregateRoot is IStandardState standardEntity)
            {
                if (standardEntity.EntityState != EntityStateOperate.IsDraft)
                    standardEntity.EntityState = EntityStateOperate.Normal;
            }
            //if (aggregateRoot is IFilter4Org orgEntity)
            //{
            //    orgEntity.OrgId = HttpContext.Current.User.Identity.GetOrgId();
            //}
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="aggregateRoot"></param>
        public virtual void Update(TAggregateRoot aggregateRoot)
        {
            if (aggregateRoot is ILogModifiEntity entity)
            {
                var info = entity;
                info.ModifiTime = DateTime.Now;
                info.ModifiedUserId = GetUserId();
            }

            #region 关联的从表应该不实现ILogCheckinEntity、ILogModifiEntity，但是个别人还是加上了，而我们不能让它报异常。
            var properties = aggregateRoot.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (var property in properties)
            {
                if (property.PropertyType.GetInterface(nameof(IEntity)) == null)
                {
                    continue;
                }
                if (property.GetValue(aggregateRoot) is ILogCreatedEntity instance)
                {
                    if (instance.CreatedTime == null)
                        instance.CreatedTime = DateTime.Now;
                    if (instance.CreatedUserId == null)
                        instance.CreatedUserId = GetUserId();
                }

                if (property.GetValue(aggregateRoot) is ILogModifiEntity instanceB)
                {
                    instanceB.ModifiTime = DateTime.Now;
                    instanceB.ModifiedUserId = GetUserId();
                }
            }
            #endregion


            _efContext.RegisterModified<TKey, TAggregateRoot>(aggregateRoot);
        }
        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual bool Exists(Expression<Func<TAggregateRoot, bool>> predicate)
        {
            return DbSet().AsNoTracking().Any(predicate);
        }
        /// <summary>
        /// 移除数据
        /// </summary>
        /// <param name="aggregateRoot"></param>
        public virtual void Remove(TAggregateRoot aggregateRoot)
        {
            if (aggregateRoot is IStandardState)
            {
                var info = Get(aggregateRoot.Id) as IStandardState;
                info.EntityState = EntityStateOperate.IsDeleted;
                _efContext.RegisterModified<TKey, TAggregateRoot>(info as TAggregateRoot);
            }
            else
            {
                _efContext.RegisterDeleted<TKey, TAggregateRoot>(aggregateRoot);
            }
        }

        /// <summary>
        /// 移除数据
        /// </summary>
        /// <param name="ids"></param>
        public virtual void Remove(IEnumerable<TKey> ids)
        {
            var infos = _efContext.Context.Set<TAggregateRoot>().Where(x => ids.Contains(x.Id)).ToList();
            if (typeof(TAggregateRoot).GetInterface(nameof(IStandardState)) == null)
            {
                _efContext.Context.Set<TAggregateRoot>().RemoveRange(infos);
            }
            else
            {
                infos.ForEach(x =>
                {
                    if (x is IStandardState info)
                    {
                        info.EntityState = EntityStateOperate.IsDeleted;
                    }

                    if (x is ILogDeleteEntity logentity)
                    {
                        logentity.DeleteTime = DateTime.Now;
                        logentity.DeleteUserId = GetUserId();
                    }
                    _efContext.RegisterModified<TKey, TAggregateRoot>(x);
                });
            }
        }

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public TAggregateRoot Get(TKey key)
        {
            return Get(key, null);
        }
        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public TAggregateRoot Get(TKey key,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            var parameter = Expression.Parameter(typeof(TAggregateRoot));

            var lamuda = Expression.Lambda<Func<TAggregateRoot, bool>>(
                Expression.Equal(Expression.Property(parameter, nameof(IEntity.Id)), Expression.Constant(key)),
                parameter);

            var query = _efContext.Context.Set<TAggregateRoot>().Where(lamuda);
            if (eagerLoadingProperties != null)
            {
                foreach (var item in eagerLoadingProperties)
                {
                    query = query.Include(item);
                }
            }
            return query.FirstOrDefault();
        }
        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate)
        {
            return Get(predicate, (int?)null, (string)null);
        }
        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate,
                   params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            return Get(predicate, null, eagerLoadingProperties);
        }
        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="top"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate,
            int? top = null,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            var queryModel = new RepositoryQueryModel<TKey, TAggregateRoot>();
            queryModel.Predicate = predicate;
            queryModel.EagerLoadingPropertiesB = eagerLoadingProperties;
            queryModel.Top = top;

            return Get(queryModel);
        }
        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="top"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public TAggregateRoot Get(Expression<Func<TAggregateRoot, bool>> predicate,
                   int? top = null,
                   params string[] eagerLoadingProperties)
        {
            var queryModel = new RepositoryQueryModel<TKey, TAggregateRoot>();
            queryModel.Predicate = predicate;
            queryModel.EagerLoadingProperties = eagerLoadingProperties;
            queryModel.Top = top;

            return Get(queryModel);
        }
        /// <summary>
        /// 根据指定的规约获取聚合根
        /// </summary>
        /// <param name="queryModel"></param>
        /// <returns></returns>
        public TAggregateRoot Get(RepositoryQueryModel<TKey, TAggregateRoot> queryModel)
        {
            var query = DbSet().Where(queryModel.Predicate);
            if (queryModel.EagerLoadingProperties != null)
            {
                foreach (var item in queryModel.EagerLoadingProperties.Where(x => x != null))
                {
                    query = query.Include(item);
                }
            }
            if (queryModel.EagerLoadingPropertiesB != null)
            {
                foreach (var item in queryModel.EagerLoadingPropertiesB.Where(x => x != null))
                {
                    query = query.Include(item);
                }
            }
            if (queryModel.Top != null)
            {
                query = query.Take(queryModel.Top.Value);
            }
            return query.FirstOrDefault();
        }
        /// <summary>
        /// 获取数据集合
        /// </summary>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList()
        {
            return GetList(x => true, "", null, (string)null);
        }

        /// <summary>
        /// 获取数据集合
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate)
        {
            return GetList(predicate, "", null, (string)null);
        }

        /// <summary>
        /// 获取数据集合
        /// </summary>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList(params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            return GetList(null, "", null, eagerLoadingProperties);
        }
        /// <summary>
        /// 获取数据集合
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="top"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate, int top, params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            return GetList(predicate, "Id DESC", top, eagerLoadingProperties);
        }

        /// <summary>
        /// 获取数据集合
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate,
            params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            return GetList(predicate, "", null, eagerLoadingProperties);
        }
        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="sort"></param>
        /// <param name="top"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate, string sort, int? top = null, params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            var queryModel = new RepositoryQueryModel<TKey, TAggregateRoot>();
            queryModel.Predicate = predicate;
            queryModel.EagerLoadingPropertiesB = eagerLoadingProperties;
            queryModel.Top = top;
            queryModel.SortPredicate = sort;

            return GetList(queryModel);
        }
        /// <inheritdoc />
        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="sort"></param>
        /// <param name="top"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList(Expression<Func<TAggregateRoot, bool>> predicate, string sort, int? top = null, params string[] eagerLoadingProperties)
        {
            var queryModel = new RepositoryQueryModel<TKey, TAggregateRoot>();
            queryModel.Predicate = predicate;
            queryModel.EagerLoadingProperties = eagerLoadingProperties;
            queryModel.Top = top;
            queryModel.SortPredicate = sort;

            return GetList(queryModel);
        }
        /// <summary>
        /// 获取聚合根
        /// </summary>
        /// <param name="queryModel"></param>
        /// <returns></returns>
        public IList<TAggregateRoot> GetList(RepositoryQueryModel<TKey, TAggregateRoot> queryModel)
        {
            var query = DbSet();
            if (queryModel.Predicate != null)
            {
                query = query.Where(queryModel.Predicate);
            }

            if (queryModel.EagerLoadingProperties != null)
            {
                foreach (var item in queryModel.EagerLoadingProperties.Where(x => x != null))
                {
                    query = query.Include(item);
                }
            }
            if (queryModel.EagerLoadingPropertiesB != null)
            {
                foreach (var item in queryModel.EagerLoadingPropertiesB.Where(x => x != null))
                {
                    query = query.Include(item);
                }
            }

            if (!queryModel.SortPredicate.IsNullOrEmpty())
            {
                query = query.OrderBy(queryModel.SortPredicate);
            }
            if (queryModel.Top != null)
            {
                query = query.Take(queryModel.Top.Value);
            }

            return query.ToList();
        }


        #region 获取分页数据
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageNo"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public PagedResult<TAggregateRoot> Pagging(int pageNo, int pageSize)
        {
            return Pagging(pageNo, pageSize, null, "ID DESC", (Expression<Func<TAggregateRoot, dynamic>>[])null);
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageNo">分页的页码。</param>
        /// <param name="pageSize">分页的页面大小。</param>
        /// <param name="sortPredicate">排序表达式</param>
        /// <returns></returns>
        public PagedResult<TAggregateRoot> Pagging(int pageNo, int pageSize, string sortPredicate)
        {
            return Pagging(pageNo, pageSize, null, sortPredicate, (Expression<Func<TAggregateRoot, dynamic>>[])null);
        }

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageNo">分页的页码。</param>
        /// <param name="pageSize">分页的页面大小。</param>
        /// <param name="predicate">筛选表达式</param>
        /// <param name="sortPredicate">排序表达式。</param>
        /// <returns>所有符合条件的已经排序的聚合根。</returns>
        public PagedResult<TAggregateRoot> Pagging(int pageNo, int pageSize,
             Expression<Func<TAggregateRoot, bool>> predicate,
             string sortPredicate)
        {
            return Pagging(pageNo, pageSize, predicate, sortPredicate, (Expression<Func<TAggregateRoot, dynamic>>[])null);
        }

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pf">分页参数</param>
        /// <returns></returns>
        public PagedResult<TAggregateRoot> Pagging(PagingFeature pf)
        {
            return Pagging(pf, null, (Expression<Func<TAggregateRoot, dynamic>>[])null);
        }

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pf"></param>
        /// <param name="predicate"></param>
        /// <param name="eagerLoadingProperties"></param>
        /// <returns></returns>
        public PagedResult<TAggregateRoot> Pagging(
            PagingFeature pf,
            Expression<Func<TAggregateRoot, bool>> predicate,
             params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            var queryModel = new RepositoryQueryModel<TKey, TAggregateRoot>();
            queryModel.Predicate = predicate;
            queryModel.EagerLoadingPropertiesB = eagerLoadingProperties;
            queryModel.Top = null;
            queryModel.SortPredicate = null;
            return Pagging(pf, queryModel);
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageNo">分页的页码。</param>
        /// <param name="pageSize">分页的页面大小。</param>
        /// <param name="predicate">筛选表达式</param>
        /// <param name="sortPredicate">排序表达式。</param>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有符合条件的已经排序的聚合根。</returns>
        public PagedResult<TAggregateRoot> Pagging(int pageNo, int pageSize,
              Expression<Func<TAggregateRoot, bool>> predicate,
              string sortPredicate,
              params Expression<Func<TAggregateRoot, dynamic>>[] eagerLoadingProperties)
        {
            var queryModel = new RepositoryQueryModel<TKey, TAggregateRoot>();
            queryModel.Predicate = predicate;
            queryModel.EagerLoadingPropertiesB = eagerLoadingProperties;
            queryModel.Top = null;
            queryModel.SortPredicate = sortPredicate;
            return Pagging(new PagingFeature(UIEngine.None) { PageNo = pageNo, PageSize = pageSize }, queryModel);
        }

        /// <inheritdoc />
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pf">分页参数</param>
        /// <param name="predicate">筛选表达式</param>
        /// <param name="sortPredicate">排序表达式。</param>
        /// <param name="eagerLoadingProperties">需要进行饥饿加载的属性Lambda表达式。</param>
        /// <returns>所有符合条件的已经排序的聚合根。</returns>
        public PagedResult<TAggregateRoot> Pagging(PagingFeature pf,
              Expression<Func<TAggregateRoot, bool>> predicate,
              string sortPredicate,
              params string[] eagerLoadingProperties)
        {
            var queryModel = new RepositoryQueryModel<TKey, TAggregateRoot>();
            queryModel.Predicate = predicate;
            queryModel.EagerLoadingProperties = eagerLoadingProperties;
            queryModel.Top = null;
            queryModel.SortPredicate = sortPredicate;
            return Pagging(pf, queryModel);
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pf">分页参数</param>
        /// <param name="queryModel">查询模型</param>
        /// <returns></returns>
        public PagedResult<TAggregateRoot> Pagging(PagingFeature pf,
            RepositoryQueryModel<TKey, TAggregateRoot> queryModel)
        {
            _efContext.Context.Configuration.LazyLoadingEnabled = false;
            _efContext.Context.Configuration.ProxyCreationEnabled = false;

           
            if (queryModel.Predicate != null)
            {
                var left = queryModel.Predicate.Parameters[0];
                var pagepredicate = new QuerySupport<TAggregateRoot>()
                {
                    Parameter = left
                }.TobuildFilter(pf);
                var expression = Expression.And(pagepredicate.Body, queryModel.Predicate.Body);

                queryModel.Predicate = Expression.Lambda<Func<TAggregateRoot, bool>>(expression, left);
            }
            else
            {
                queryModel.Predicate = new QuerySupport<TAggregateRoot>().TobuildFilter(pf);
            }

            var query = DbSet().AsNoTracking();
            if (queryModel.Predicate != null)
            {
                query = query.Where(queryModel.Predicate);
            }

            if (queryModel.EagerLoadingProperties != null)
            {
                foreach (var item in queryModel.EagerLoadingProperties)
                {
                    query = query.Include(item);
                }
            }
            if (queryModel.EagerLoadingPropertiesB != null)
            {
                foreach (var item in queryModel.EagerLoadingPropertiesB.Where(x => x != null))
                {
                    query = query.Include(item);
                }
            }
            if (queryModel.SortPredicate.IsNullOrEmpty() || queryModel.SortPredicate.Equals("ID DESC", StringComparison.CurrentCultureIgnoreCase))
            {
                query = query.OrderByDescending(x => x.Id);
            }
            else if (queryModel.SortPredicate.Equals("ID ASC", StringComparison.CurrentCultureIgnoreCase))
            {
                query = query.OrderBy(x => x.Id);
            }
            else
            {
                query = query.OrderBy(queryModel.SortPredicate);
            }

            return new PagedResult<TAggregateRoot>(query, pf.PageSize, pf.PageNo);
        }
        #endregion

        #region 统计
        /// <summary>
        /// 计算数据量
        /// </summary>
        /// <returns></returns>
        public int Count()
        {
            return Count(null);
        }
        /// <summary>
        /// 计算数据量
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public int Count(Expression<Func<TAggregateRoot, bool>> predicate)
        {
            var query = DbSet();
            if (predicate != null)
            {
                query = query.Where(predicate);
            }

            return query.Count();
        }
        #endregion

        #region 去重
        /// <summary>
        /// 去重
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public IEnumerable<TAggregateRoot> Distinct(Expression<Func<TAggregateRoot, bool>> predicate)
        {
            var query = DbSet();
            if (predicate != null)
            {
                query = query.Where(predicate);
            }

            return query.Distinct();
        }
        #endregion

        #region 分组
        /// <summary>
        /// 分组
        /// </summary>
        /// <typeparam name="TGKey"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="keySelector"></param>
        /// <param name="resultSelector"></param>
        /// <returns></returns>
        public IEnumerable<TResult> GroupBy<TGKey, TResult>(
            Expression<Func<TAggregateRoot, bool>> predicate,
            Expression<Func<TAggregateRoot, TGKey>> keySelector,
            Expression<Func<TGKey, IEnumerable<TAggregateRoot>, TResult>> resultSelector)
        {
            var query = DbSet();

            if (predicate != null)
            {
                query = query.Where(predicate);
            }

            return query.GroupBy(keySelector, resultSelector);
        }
        #endregion

        #region 修正数据
        /// <summary>
        /// 修正数据
        /// </summary>
        /// <param name="root"></param>
        private void FixData(TAggregateRoot root)
        {
            foreach (var p in root.GetType().GetProperties())
            {
                if (p.PropertyType.IsAssignableFrom(typeof(DateTime)))
                {
                    if (p.GetValue(root) == null) continue;
                    if ((DateTime)p.GetValue(root) == DateTime.MinValue)
                    {
                        p.SetValue(root, null);
                    }
                }
            }
        }

        #endregion


        #region 筛选指定数据
        /// <summary>
        /// 筛选指定数据
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="selector"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        public TResult SelectFirst<TResult>(Expression<Func<TAggregateRoot, bool>> predicate, Expression<Func<TAggregateRoot, TResult>> selector, int? top = null)
        {
            var query = DbSet().Where(predicate);

            if (top != null)
            {
                query = query.Take(top.Value);
            }
            return query.Select(selector).First();
        }
        /// <summary>
        /// 筛选指定数据
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="selector"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        public TResult SelectFirstOrDefault<TResult>(Expression<Func<TAggregateRoot, bool>> predicate, Expression<Func<TAggregateRoot, TResult>> selector, int? top = null)
        {
            var query = DbSet().Where(predicate);

            if (top != null)
            {
                query = query.Take(top.Value);
            }
            return query.Select(selector).FirstOrDefault();
        }
        /// <summary>
        /// 筛选指定数据
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="selector"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        public IEnumerable<TResult> Select<TResult>(Expression<Func<TAggregateRoot, bool>> predicate, Expression<Func<TAggregateRoot, TResult>> selector, int? top = null)
        {
            var query = DbSet().Where(predicate);

            if (top != null)
            {
                query = query.Take(top.Value);
            }
            return query.Select(selector).AsEnumerable();
        }

        #endregion

        private int? GetUserId()
        {
#if NET462
            return HttpContext.Current.User.Identity.GetUserId();
#else
            return null;
#endif
        }

    }

    /// <summary>
    /// 仓储基类
    /// </summary>
    /// <typeparam name="TAggregateRoot"></typeparam>
    public partial class Repository<TAggregateRoot> : Repository<Guid, TAggregateRoot>
        where TAggregateRoot : class, IAggregateRoot<Guid>
    {
        /// <summary>
        /// 仓储基类
        /// </summary>
        /// <param name="context"></param>
        public Repository(IRepositoryContext context)
            : base(context)
        {

        }
    }


}